package com.ali.ttt.netty.common.listener;

import cn.hutool.core.util.StrUtil;
import com.ali.ttt.netty.common.domain.Message;
import com.ali.ttt.netty.common.intface.InMessage;
import com.alibaba.fastjson.JSONObject;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Component
public class MessageListenerProcessor {
    @Resource
    private ApplicationContext applicationContext;

    public void processMessage(Message msg,ChannelHandlerContext ctx) {
        if(msg!=null){
            String path = msg.getPath();
            if(StrUtil.isNotEmpty(path)){
                Map<String, Object> beansOfType = applicationContext.getBeansOfType(Object.class);
                for (Map.Entry<String, Object> entry : beansOfType.entrySet()) {
                    Object bean = entry.getValue();
                    for (Method method : bean.getClass().getDeclaredMethods()) {
                        if (method.isAnnotationPresent(InMessage.class)) {
                            InMessage listener = method.getAnnotation(InMessage.class);
                            if (listener.path().equals(path)) {
                                try {
                                    Type[] genericParameterTypes = method.getGenericParameterTypes();
                                    ParameterizedType parameterizedType = (ParameterizedType) genericParameterTypes[0];
                                    Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                                    msg.setMsg(JSONObject.parseObject(JSONObject.toJSONString(msg.getMsg()), actualTypeArguments[0]));
                                    msg.setCtx(ctx);
                                    method.invoke(bean, msg);
                                } catch (IllegalAccessException | InvocationTargetException e) {
                                    throw new RuntimeException(e);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
